package cn.edu.dgut.sai.file;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Sai
 * Created by Sai on 2019-03-03.
 */
@WebServlet("/multiUpload")
// location改为本地的绝对路径，目录必须已存在，否则报IOE
@MultipartConfig(location = "/Users/sai/Downloads")
public class MultiUploadServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 如果前端页面的字符编码为UTF-8,这里可以不写。
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        // Content-Type != multipart/form-data
        // 文件上传的http请求的Content-Type的格式为：multipart/form-data; boundary=----WebKitFormBoundary0jDwWc6AbnD3yBRr
        if (request.getContentType() == null || !request.getContentType().startsWith("multipart/form-data")) {
            response.getWriter().write("错误：http请求的ContentType必须为multipart/form-data");
            return;
        }

        /*
            Part{n=upload,fn=null,ct=null,s=6,t=true,f=null}
            Part{n=file2,fn=短信接口文档.zip,ct=application/zip,s=3001812,t=true,f=null}
            Part{n=file1,fn=授权证明.doc,ct=application/msword,s=26112,t=true,f=null}
            如上：form表单中的按钮<input>组件的值也会上传过来，getSubmittedFileName()获取的文件名为null,所以要过滤掉。

            Part{n=file2,fn=,ct=application/octet-stream,s=0,t=true,f=null}
            如上：前端form表单中的文件组件<input>如果没有选择文件，也会传值过来，并且getSubmittedFileName()获取的文件名为空字符串"",所以也要过滤掉。

            同理，其它的<input>标签的组件，也会一并传值到后端，不管他有没有传值，如文本框组件。注意观察Part封装内容。
            文本框的part: Part{n=fix,fn=null,ct=null,s=5,t=true,f=null}


            对于非文件域的字段，如：text文本框、按钮、隐藏字段的value值，可以通过part.getInputStream()可以获得<input>的value的值.
            思考：InputStream如何转换String,从而获得text文本框的字符串的值？？

            2019-3-10更新：
            Servlet 3.0之前，当表单的编码格式为multipart/form-data，不能使用request.getParameter()获取传参的值;
            但到了Servlet 3.0之后，表单文件上传的同时，包含有text文本框，是可以通过request.getParameter()获取的，但文件域依然是不行，需要通过part.
            servlet 3.0规范地址：
            https://download.oracle.com/otndocs/jcp/servlet-3.0-fr-eval-oth-JSpec/
            第44页里面有说明：par里如果没有filename的（fn=null），可以从getParameter / getParameterValues 里通过name获取值。
            测试：
            在前端文件上传表单增加一个text文本框
            System.out.println(request.getParameter("text_name") );
            System.out.println(request.getParameter("upload") );
        */
        List<String> filesName = new ArrayList<>();

        request.getParts().stream()
                .filter(part -> part.getSubmittedFileName() != null && !part.getSubmittedFileName().equals(""))
                .forEach(part -> {
                    System.out.println(part);// 打印、观察每个part对象
                    System.out.println("上传文件的文件名：" + part.getSubmittedFileName());
                    try {
                        // 调用Part.write方法，把文件写入本地文件系统。
                        part.write(part.getSubmittedFileName());
                        filesName.add(part.getSubmittedFileName());

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });

        if (filesName.size() < 1) {
            response.getWriter().write("文件上传失败！");
            return;
        }

        response.getWriter().write(String.join(",", filesName) + ": 文件上传成功!!");

    }
}
